package com.hulk.rpc.config.server;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.hulk.rpc.annotation.HulkService;
import com.hulk.rpc.config.common.ConfigUtils;
import com.hulk.rpc.config.common.HostPort;
import com.hulk.rpc.registry.ServerRegistry;
import com.typesafe.config.Config;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author xuxukang
 */
@Data
@Accessors(chain = true)
public class RegistryConfig {

  private final HostPort serverAddress;
  private final int serverWeight;
  private final ProtocolType protocolType;
  private final ServerRegistry serverRegistry;

  /**
   * 解析RegistryConfig列表配置
   *
   * @param configs 配置文件中"registries"的配置列表
   */
  public static List<RegistryConfig> parseList(List<? extends Config> configs) {
    List<RegistryConfig> registryConfigs = Lists.newArrayList();
    configs.parallelStream().forEachOrdered(config -> {
      RegistryConfig registryConfig = parseSingle(config);
      registryConfigs.add(registryConfig);
    });

    return registryConfigs;
  }

  /**
   * 解析单个registry配置
   *
   * @param config registers列表中的一个
   */
  public static RegistryConfig parseSingle(Config config) {
    Preconditions.checkNotNull(config);

    String registryType = ConfigUtils.getStringOrElse(config, "registry.type",
            ServerRegistry.ServerRegistryEnum.local.name());
    List<String> registryAddresses = ConfigUtils.getStringListOrElse(config, "registry.address", List.of());

    String protocol = ConfigUtils.getStringOrElse(config, "server.protocol", ProtocolType.rpc.name());
    String serverAddress = ConfigUtils.getStringOrElse(config, "server.address", null);
    Preconditions.checkState(StringUtils.isNotBlank(serverAddress));
    int serverWeight = ConfigUtils.getIntOrElse(config, "server.weight", HulkService.default_weight);

    ServerRegistry.ServerRegistryEnum registryEnum = ServerRegistry.ServerRegistryEnum
            .match(registryType, ServerRegistry.ServerRegistryEnum.local);
    ServerRegistry serverRegistry = registryEnum.getServerRegistry();
    List<HostPort> hostPorts = registryAddresses.parallelStream()
            .map(HostPort::new)
            .collect(Collectors.toList());
    serverRegistry.init(hostPorts);

    return new RegistryConfig(new HostPort(serverAddress), serverWeight,
            ProtocolType.valueOf(protocol), serverRegistry);
  }

}
